using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace Yoozoo.Gameplay.Liberty.AI
{
    public partial class AnimationEventEditor
    {
        // 人物列表
        private string[] _CharacterIDs;
        // 状态名列表
        private string[] _StateNames;
        // 状态显示名列表 (包含Layer，怕菜单中选择时重名不好辨认)
        private string[] _ShowStateNames;
        // 状态Layer列表
        private int[] _StateLayers;
        
        // 节点列表面板宽度 (左)
        private const int k_HierarchyPanelWidth = 250;    
        // 详细属性面板宽度 (右)
        private const int k_InspectorPanelWidth = 250;
        // Timeline面板宽度 (中)
        private int k_TimelinePanelWidth = 0;
        // Timeline数据元素高度
        private const int k_ElementHeight = 20;
        // 滚动层偏移
        private Vector2 _HierarchyScrollPosition;
        private Vector2 _InspectorScrollPosition;
        // 当前是否正在播放 (用于编辑器模式控制查看动画)
        private bool _IsPlaying = false;
        // 是否循环播放
        private bool _IsLoop = true;
        // 当前播放到第几帧
        private int _CurrentFrame = 0;
        // 当前动画计时器
        private float _AnimationTimer = 0;
        
        // 选择人物ID
        private string _SelectedCharacterID = string.Empty;
        // 选择动画
        private string _SelectedState = string.Empty;
        
        // 人物guid
        private string _MainCharacterResourceGuid;
        private GameObject _MainCharacterResource;
        // 人物GameObject
        private GameObject _MainCharacter;
        // 人物Animator组件
        private Animator _Animator;
        // 当前播放动画的layer
        private int _AnimatorLayer = 0;
        // 当前选择的动画文件
        private AnimationClip _AnimationClip = null;
        // 
        private bool _ApplyRootMotion = false;
        // 当前动画总帧数
        private int _TotalFrames = 0;
        // 当前所有动画事件
        private AnimationEvent[] _AnimationEvents = null;
        
        // 选中Item的index
        private int _SelectedItemIndex = -1;

        
        
        // Toolbar高度
        const int k_ToolbarHeight = 18;
        // Timeline刻度尺每点间隔（包含小点）
        const float k_TickGap = 10;
        // Timeline刻度尺小刻度数量
        const int k_TickUnit = 5;
        // Timeline刻度尺水平偏移
        const float k_RulerOffsetX = 10;
        
        // GUIContent
        // 播放按钮
        static readonly GUIContent k_PlayFramesContent = EditorGUIUtility.IconContent("Animation.Play", "Play");
        // 暂停
        static readonly GUIContent k_PauseFrameContent = EditorGUIUtility.IconContent("PauseButton", "Pause");
        // 上一帧
        static readonly GUIContent k_PreviousFrameContent = EditorGUIUtility.IconContent("Animation.PrevKey", "Previous Key Frame");
        // 下一帧
        static readonly GUIContent k_NextFrameContent = EditorGUIUtility.IconContent("Animation.NextKey", "Next Key Frame");
        // 第一帧
        static readonly GUIContent k_FirstFrameContent = EditorGUIUtility.IconContent("Animation.FirstKey", "First Key Frame");
        // 最后一帧
        static readonly GUIContent k_LastFrameContent = EditorGUIUtility.IconContent("Animation.LastKey", "Last Key Frame");
        // 循环
        static readonly GUIContent k_LoopFrameContent = EditorGUIUtility.IconContent("preAudioLoopOff", "Loop");
        // +
        static readonly GUIContent k_ToolbarPlus = EditorGUIUtility.TrIconContent("Toolbar Plus", "Add to the list");
        // -
        static readonly GUIContent k_ToolbarMinus = EditorGUIUtility.TrIconContent("Toolbar Minus", "Remove selection from the list");
        
        // GUIStyle
        public static readonly GUIStyle k_Label = new GUIStyle("label");
        public static readonly GUIStyle k_BoldLabel = new GUIStyle("BoldLabel");
        public static readonly GUIStyle k_TimelineRuler = new GUIStyle("MeTimeLabel");
        public static readonly GUIStyle k_FrameBackground = new GUIStyle("FrameBox");
        public static readonly GUIStyle k_WindowBackground = new GUIStyle("OL box NoExpand");
        public static readonly GUIStyle k_HelpBox = new GUIStyle("HelpBox");
        public static readonly GUIStyle k_BackgroundSelected = new GUIStyle("OL SelectedRow");
        public static readonly GUIStyle k_BackgroundEven = new GUIStyle("OL EntryBackEven");
        public static readonly GUIStyle k_TimelineBlockLeft = new GUIStyle("MeTransOnLeft");
        public static readonly GUIStyle k_TimelineBlockRight = new GUIStyle("MeTransOnRight");
        public static readonly GUIStyle k_TimelineFrameTag = new GUIStyle("Grad Down Swatch");
        public static readonly GUIStyle k_Foldout = new GUIStyle("foldout");
        public static readonly GUIStyle k_DropDownButton = new GUIStyle("DropDown");
        public static readonly GUIStyle k_ACButton = new GUIStyle("AC Button");
        
        
        static AnimationEventEditor()
        {
            // k_Label
            k_Label.alignment = TextAnchor.LowerCenter;
            k_Label.stretchHeight = true;
            k_Label.margin.top = 0;
            k_Label.margin.bottom = 0;
            // k_BackgroundSelected
            k_BackgroundSelected.fixedHeight = 0;
            k_BackgroundSelected.stretchHeight = true;
            // k_BackgroundEven
            k_BackgroundEven.fixedHeight = 0;
            k_BackgroundEven.stretchHeight = true;
            // k_TimelineBlockLeft
            k_TimelineBlockLeft.fixedHeight = 0;
            k_TimelineBlockLeft.fixedWidth = 0;
            k_TimelineBlockLeft.stretchWidth = true;
            k_TimelineBlockLeft.stretchHeight = true;
            // k_TimelineBlockRight
            k_TimelineBlockRight.fixedHeight = 0;
            k_TimelineBlockRight.fixedWidth = 0;
            k_TimelineBlockRight.stretchHeight = true;
            k_TimelineBlockRight.stretchWidth = true;
            // k_ACButton
            k_ACButton.fixedHeight = 0;
            k_ACButton.fixedWidth = 0;
            k_ACButton.stretchWidth = true;
            k_ACButton.stretchHeight = true;
            // k_DropDownButton
            k_DropDownButton.margin.top = 0;
            k_DropDownButton.stretchHeight = true;

            RectOffset offset = new RectOffset(0,0,0,0);
            // k_WindowBackground
            k_WindowBackground.margin = offset;
            k_WindowBackground.padding = offset;
            k_WindowBackground.border = offset;
            k_WindowBackground.padding.top = 1;
            // k_HelpBox
            k_HelpBox.margin = offset;
            k_HelpBox.padding = offset;
            k_HelpBox.border = offset;
            k_HelpBox.padding.top = 1;
            // k_BackgroundSelected 
            k_BackgroundSelected.margin = offset;
            k_BackgroundSelected.padding = offset;
            k_BackgroundSelected.border = offset;
            // k_BackgroundEven
            k_BackgroundEven.margin = offset;
            k_BackgroundEven.padding = offset;
            k_BackgroundEven.border = offset;
            // k_Foldout
            k_Foldout.margin.top = 0;
            k_Foldout.margin.bottom = 0;
            k_Foldout.margin.left -= 10;
            k_Foldout.margin.right += 2;
            k_Foldout.fixedHeight = 20;
        }
        
        /// <summary>
        /// 计算timeline的矩形Rect
        /// </summary>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <param name="elementHeight"></param>
        /// <returns></returns>
        public static Rect CalculateTimeRect(int begin, int end, int elementHeight = 20)
        {
            float xMin = CalculateFrameToPosition(begin);
            float xMax = CalculateFrameToPosition(end);
            return new Rect(xMin, 0, xMax-xMin, elementHeight);        
        }
        /// <summary>
        /// 计算timeline帧位置
        /// </summary>
        /// <param name="frame"></param>
        /// <returns></returns>
        public static float CalculateFrameToPosition(int frame)
        {
            return k_RulerOffsetX + frame * k_TickGap;
        }

        public static int CalculatePositionToFrame(float position)
        {
            return (int) ((position - k_RulerOffsetX) / k_TickGap);
        }

        /// <summary>
        /// 下拉菜单
        /// </summary>
        /// <param name="texts"></param>
        /// <param name="selectedIndex"></param>
        /// <param name="callback"></param>
        public static void CreateMenu(string[] texts, int selectedIndex, System.Action<int> callback)
        {
            if (texts == null)
            {
                return;
            }
            GenericMenu menu = new GenericMenu();
            for (int i = 0; i < texts.Length; ++i)
            {
                menu.AddItem(new GUIContent(texts[i]), i==selectedIndex, (userdata) =>
                {
                    int index = (int)userdata;
                    if (index >= 0)
                    {
                        callback?.Invoke(index);
                    }
                }, i);
            }
            menu.ShowAsContext();
        }
        
        // 通过枚举创建菜单
        public static void CreateMenu<T>(int selectedIndex, System.Action<int> callback) where T : Enum
        {
            List<string> texts = new List<string>();
            foreach (var e in Enum.GetValues(typeof(T)))
            {
                texts.Add(((T)e).GetDescription());
            }

            GenericMenu menu = new GenericMenu();
            for (int i = 0; i < texts.Count; ++i)
            {
                menu.AddItem(new GUIContent(texts[i]), i==selectedIndex, (userdata) =>
                {
                    int index = (int)userdata;
                    if (index >= 0)
                    {
                        callback?.Invoke(index);
                    }
                }, i);
            }
            menu.ShowAsContext();
        }
        public static void CreateMenu<T>(T eSelectedIndex, System.Action<int> callback) where T : Enum
        {
            int selectedIndex = -1;

            Type type = eSelectedIndex.GetType();
            List<string> texts = new List<string>();
            int idx = 0;
            foreach (var e in Enum.GetValues(type))
            {
                texts.Add(((T)e).GetDescription());
                if (Enum.GetName(type, e) == Enum.GetName(type, eSelectedIndex))
                {
                    selectedIndex = idx;
                }
                idx++;
            }

            
            GenericMenu menu = new GenericMenu();
            for (int i = 0; i < texts.Count; ++i)
            {
                menu.AddItem(new GUIContent(texts[i]), i==selectedIndex, (userdata) =>
                {
                    int index = (int)userdata;
                    if (index >= 0)
                    {
                        callback?.Invoke(index);
                    }
                }, i);
            }
            menu.ShowAsContext();
        }

        /// <summary>
        /// 检测ui数据是否发生改变
        /// </summary>
        public class GUIChangeCheck : IDisposable
        {
            private System.Action _callback;
        
            public GUIChangeCheck(System.Action callback)
            {
                EditorGUI.BeginChangeCheck();
                this._callback = callback;
            }

            public void Dispose()
            {
                if (EditorGUI.EndChangeCheck())
                {
                    this._callback?.Invoke();
                }
            }
        }
        
        /// <summary>
        /// 区域排版
        /// </summary>
        public class GUILayoutArea : IDisposable
        {
            public GUILayoutArea(Rect rect)
            {
                GUILayout.BeginArea(rect);
            }
            public GUILayoutArea(Rect rect, string text)
            {
                GUILayout.BeginArea(rect, text);
            }
            public GUILayoutArea(Rect rect, Texture image)
            {
                GUILayout.BeginArea(rect, image);
            }
            public GUILayoutArea(Rect rect, GUIStyle style)
            {
                GUILayout.BeginArea(rect, style);
            }
            public void Dispose()
            {
                GUILayout.EndArea();
            }
        }
        
        /// <summary>
        /// 滚动排版
        /// </summary>
        public class GUILayoutScrollView : IDisposable
        {
            public GUILayoutScrollView(ref Vector2 scrollPosition)
            {
                scrollPosition = GUILayout.BeginScrollView(scrollPosition);
            }
            public GUILayoutScrollView(ref Vector2 scrollPosition, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options)
            {
                scrollPosition = GUILayout.BeginScrollView(scrollPosition, horizontalScrollbar, verticalScrollbar, options);
            }
            public GUILayoutScrollView(Vector2 scrollPosition)
            {
//            GUILayout.BeginScrollView(scrollPosition);
                GUILayout.BeginScrollView(scrollPosition, GUIStyle.none, GUIStyle.none);
            }
        
            public void Dispose()
            {
                GUILayout.EndScrollView();
            }
        }

        /// <summary>
        /// 水平排版
        /// </summary>
        public class GUILayoutHorizontal : IDisposable
        {
            public GUILayoutHorizontal(params GUILayoutOption[] options)
            {
                GUILayout.BeginHorizontal(options);
            }
            public GUILayoutHorizontal(GUIStyle style, params GUILayoutOption[] options)
            {
                GUILayout.BeginHorizontal(style, options);
            }
            public GUILayoutHorizontal(string text, GUIStyle style, params GUILayoutOption[] options)
            {
                GUILayout.BeginHorizontal(text, style, options);
            }
            public void Dispose()
            {
                GUILayout.EndHorizontal();
            }
        }

        /// <summary>
        /// 垂直排版
        /// </summary>
        public class GUILayoutVertical : IDisposable
        {
            public GUILayoutVertical(params GUILayoutOption[] options)
            {
                GUILayout.BeginVertical(options);
            }
            public GUILayoutVertical(GUIStyle style, params GUILayoutOption[] options)
            {
                GUILayout.BeginVertical(style, options);
            }
            public GUILayoutVertical(string text, GUIStyle style, params GUILayoutOption[] options)
            {
                GUILayout.BeginVertical(text, style, options);
            }
            public void Dispose()
            {
                GUILayout.EndVertical();
            }
        }
        
        /// <summary>
        /// 临时替换Handles.Color
        /// </summary>
        public class GUIHandlesColor : IDisposable
        {
            private Color srcColor;

            public GUIHandlesColor(Color color)
            {
                srcColor = Handles.color;
                Handles.color = color;
            }

            public void Dispose()
            {
                Handles.color = srcColor;
            }
        }
        
    }

}

